#include <iostream>
#include "fenetreimage.h"
#include "ui_fenetreimage.h"
#include "mainwindow.h"
#include "maqgraphicsscene.h"
FenetreImage::FenetreImage(QWidget *parent, Calque *image,QString selectedImage) :
    QFrame(parent),
    ui(new Ui::FenetreImage)
{
    //Fenetrage
    ui->setupUi(this);
    mainWindow = (MainWindow*) parent;
    mainWindow->getMdiArea()->addSubWindow(this);

    hauteur = image->height();
    largeur = image->width();
    scene = new MaQGraphicsScene(QRect(0,0,largeur,hauteur),ui->VueImage);

    //Fond cadrillage
    QImage imageFond = QImage(":new/Images/fond.png");
    QBrush brushfond = QBrush(imageFond);
    fond = new QGraphicsRectItem(0,0, largeur, hauteur);
    fond->setBrush(brushfond);
    fond->setFlags(QGraphicsItem::ItemIgnoresTransformations);
    scene->addItem(fond);

    //Image dans la fentre
    vectCalques.reserve(10);
    vectCalques.push_back(image);
    vectPmItems.reserve(10);

    QPixmap pixMap = QPixmap::fromImage(*image);
    QGraphicsPixmapItem* pmItem = scene->addPixmap(pixMap);
    vectPmItems.push_back(pmItem);
    indexCourant=0;

    a_ete_modifie = false;

    //vue
    //ui->VueImage->setResizeAnchor(QGraphicsView::AnchorViewCenter);
    ui->VueImage->setScene(scene);
    ui->VueImage->setStyleSheet("background: transparent; border: none");
    ui->VueImage->setMaScene(scene);
    mainWindow->setCentralWidget(mainWindow->getMdiArea());

    //Nom de la fenetre
    chemin = selectedImage;
    int longNomImage = chemin.size();
    int y = chemin.lastIndexOf("/",longNomImage-1);
    nom = chemin.right(longNomImage-y-1);
    QString titre   = nom;
    this->setWindowTitle(titre.append(" (").append(QString::number(largeur)).append("x").append(QString::number(hauteur)).append(")"));

    // ecouteur de souris
    this->monEcouteur   = new EcouteurSourisGraphicsView(this);

    historique.setMainWindow(mainWindow);
    mainWindow->incrementeNbSousFenetre();
}

FenetreImage::~FenetreImage()
{
    while(!vectPmItems.empty()){
        delete vectPmItems.back();
        vectPmItems.pop_back();
    }
    while(!vectCalques.empty()){
        delete vectCalques.back();
        vectCalques.pop_back();
    }
    delete fond;
    scene->clear();
    delete scene;
    delete monEcouteur;
    delete ui;

}

void FenetreImage::on_fenetreMoins_clicked()
{
    ui->VueImage->scale(0.66,0.66);
    ui->spinBox->stepDown();
    ui->VueImage->adjustSize();
}

void FenetreImage::on_fenetrePlus_clicked()
{
    ui->VueImage->scale(1.5,1.5);
    ui->spinBox->stepUp();
    ui->VueImage->adjustSize();
}

void FenetreImage::closeEvent(QCloseEvent* event)
{
    //sauvegarde des images si nécessaire
    bool fermer = true ;
     if(a_ete_modifie){
         //si l image a ete modifie on l enregistre avant de fermer
         fermer = mainWindow->getActionFichier()->ActionFermerImage(this);
     }
     if(!fermer){
         //si la fermeture est annulee
         event->ignore() ;
     }else{
         ///sinon on la ferme
         event->accept();
         mainWindow->decrementeNbSousFenetre();
     }
}

void FenetreImage::on_spinBox_valueChanged(int arg1)
{
    setZoom(arg1);
    curScale();
}

void FenetreImage::setCalqueVisible(bool vis, int index)
{
    //si la visibilité du calque change, on reactualise la visu
    Calque* c = vectCalques.at(index);
    if(c->isVisible() != vis) {
        c->setVisible(vis);

        if(vis) {
            vectPmItems[index]->show();
            // le calque est rendu visible
//            QPixmap pixMap = QPixmap::fromImage(*vectCalques.at(index));
//            vectPmItems[index] = scene->addPixmap(pixMap);
        }else {
            // le calque est rendu invisible
            vectPmItems[index]->hide();
//            QGraphicsPixmapItem* pmItem = vectPmItems.at(index);
//            delete pmItem;
        }
        updateImage();
    }
}

void FenetreImage::setOpaciteCalqueCourant(int o) {
    getCalqueCourant()->setOpacite(o);

    QGraphicsPixmapItem* pmItem = vectPmItems.at(indexCourant);
    pmItem->setOpacity(o/100.0);
    updateVisu();
}


void FenetreImage::setImage(QImage * im, int indice) {
    indice=indexCourant;
    Calque* aremplacer = vectCalques.at(indice);
    QPainter p(aremplacer);
    p.drawImage(0,0, *im);

    updateCalqueCourant();
}

void FenetreImage::setIndexCourant(int i){
    indexCourant=i;
}

int FenetreImage::getIndexCourant(){
    return indexCourant;
}

Calque* FenetreImage::getCalqueCourant(){
    return vectCalques.at(indexCourant);

}

Calque* FenetreImage::getCalqueCourantMoinsUn(){
    return vectCalques.at(indexCourant-1);

}


QGraphicsItem* FenetreImage::getGraphItemCourant() {
    return vectPmItems.at(indexCourant);
}

void FenetreImage::supprimerCalqueCourant()
{
    if(vectCalques.size() > 1) {
        Calque* calqueASupprimer;
        QGraphicsPixmapItem* PmItemASupprimer;
        calqueASupprimer = vectCalques.at(indexCourant);
        PmItemASupprimer = vectPmItems.at(indexCourant);

        vector<Calque*>::iterator ItVect = vectCalques.begin();
        vector<QGraphicsPixmapItem*>::iterator ItPm = vectPmItems.begin();
        ItVect += indexCourant;
        ItPm += indexCourant;
        vectCalques.erase(ItVect);
        vectPmItems.erase(ItPm);

        delete calqueASupprimer;
        delete PmItemASupprimer;

        if(indexCourant!=0) {
            indexCourant--;
        }
    }
}

void FenetreImage::changerCalqueCourant(Calque * nouveauCalque){

    this->largeur   = nouveauCalque->width();
    this->hauteur   = nouveauCalque->height();

    //on actualise la taille de l'image dans le titre
    QString titre   = nom;
    this->setWindowTitle(titre.append(" (").append(QString::number(largeur)).append("x").append(QString::number(hauteur)).append(")"));

    //on recup et suppr le pixmap du calc que l on modifie
    QGraphicsPixmapItem* pmItem = vectPmItems.at(indexCourant);
    scene->removeItem(pmItem);
    delete pmItem;

    //on efface la scene
    scene->clear();

    //on remet Fond cadrillage
    QImage imageFond = QImage(":new/Images/fond.png");
    QBrush brushfond = QBrush(imageFond);
    fond = new QGraphicsRectItem(0,0, largeur, hauteur);
    fond->setBrush(brushfond);
    fond->setFlags(QGraphicsItem::ItemIgnoresTransformations);
    scene->addItem(fond);

    //on met le nouveau calque
    vectCalques.at(indexCourant) = nouveauCalque;
    QPixmap pixMap = QPixmap::fromImage(*nouveauCalque);
    vectPmItems.at(indexCourant) = scene->addPixmap(pixMap);

    //on le déplace à sa position
    QGraphicsItem* item = this->getGraphItemCourant();
    item->moveBy(nouveauCalque->getPosX(),nouveauCalque->getPosY());

    //on redimensionne
    scene->setSceneRect(0,0,largeur, hauteur);
    updateImage();
}

void FenetreImage::nouveauCalque()
{
    QImage::Format format= QImage::Format_ARGB32;
    Calque * courant        = this->getCalqueCourant();
    Calque* nouveauCalque   = new Calque(courant->width(), courant->height(), format);
    ajouterCalque(nouveauCalque);
}


void FenetreImage::updateCalqueCourant() {
    //on recup et suppr le pixmap du calc modifie
    QGraphicsPixmapItem* pmItem = vectPmItems.at(indexCourant);
    delete pmItem;
    //et on le remplace par un nouveau depuis le calque modifie
    Calque * imageCourante  = vectCalques.at(indexCourant);

    QPixmap pixMap = QPixmap::fromImage(*imageCourante);
     this->vectPmItems.at(indexCourant)= scene->addPixmap(pixMap);

    //on la met à sa position
    QGraphicsItem* item = this->getGraphItemCourant();
    item->moveBy(imageCourante->getPosX(),imageCourante->getPosY());

    updateImage();
}


void FenetreImage::updateImage()
{
    //Met a jour l'affichage de l'image
    vector<Calque*>::iterator It;
    for(It = vectCalques.begin(); It != vectCalques.end(); It++) {
        (*It)->updateInfo();
    }
    repaintVisu();
}




//////// scale /////////
qreal FenetreImage::curScale() {
    return  ui->VueImage->transform().m11();
}

void FenetreImage::scaleBy(qreal scaleFactor)
{
    qreal curScaleFactor = this->curScale();

    // si on est aux extremes
    if (((curScaleFactor == minScale) && (scaleFactor < 1.0)) ||
            ((curScaleFactor == maxScale) && (scaleFactor > 1.0))) return;

    qreal sc = scaleFactor;
    if ((curScaleFactor * sc < minScale)&&(sc < 1.0)) {
        sc = minScale / curScaleFactor;
    } else {
        if ((curScaleFactor * sc > maxScale)&&(sc > 1.0)) {
            sc = maxScale / curScaleFactor;
        }
    }
    ui->VueImage->scale(sc, sc);
}

void FenetreImage::setZoom(int percentZoom)
{
    qreal targetScale = (qreal)percentZoom / 100.0;
    qreal scaleFactor = targetScale / ui->VueImage->transform().m11();
    scaleBy(scaleFactor);
}

///// redessinage /////
void FenetreImage::repaintVisu(){
    mainWindow->histogramme->repaint();
    mainWindow->listecalques->reactu();
    mainWindow->historique->reactu();
}

void FenetreImage::updateVisu() {
}

MainWindow * FenetreImage::getMaMainWindow(){
    return mainWindow;
}

EcouteurSourisGraphicsView * FenetreImage::getMonEcouteur(){
    return this->monEcouteur;

}

Ui::FenetreImage * FenetreImage::getMonUi(){
    return this->ui;
}

MaQGraphicsScene * FenetreImage::getMaScene(){
    return scene;
}

void FenetreImage::afficheCouleur(QRgb couleur){
    mainWindow->couleur->changeCouleur(couleur);
    mainWindow->couleur->repaint();
}

void FenetreImage::ajouterCalque(Calque * aInserer){
    std::vector<Calque*>::iterator it1              = this->vectCalques.begin();
    std::vector<QGraphicsPixmapItem*>::iterator it2 = this->vectPmItems.begin();

    this->indexCourant++;
    this->vectCalques.insert(it1+this->indexCourant, aInserer);

    QPixmap pixMap = QPixmap::fromImage(*aInserer);
    QGraphicsPixmapItem* pmItem = scene->addPixmap(pixMap);
    this->vectPmItems.insert(it2+this->indexCourant, pmItem);

    this->updateImage();
}
